<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <script>
    // 阶段 1：JavaScript 核心能力
    // 手写 深拷贝（处理循环引用、Symbol、Map/Set）
    const deepClone = target => {
      if (typeof target !== 'Object' || traget === null) {
        return target;
      }
      let res;
      if (Array.isArray(target)) {
        res = [];
        for (const i of target) {
          res.push(deepClone(i));
        }
      } else if (target.construcor === RegExp || target.construcor === Date) {
        res = target;
      } else {
        res = {};
        for (const key in target) {
          if (target.hasOwnProperty(key)) {
            res[key] = deepClone(target[key]);
          }
        }
      }
      return res;
    };

    function deepClone(target, hash = new WeakMap()) {
      // 处理基本类型、null、undefined、函数（函数直接返回，不拷贝）
      if (target === null || typeof target !== 'object') {
        return target;
      }
      // 处理循环引用：如果已经拷贝过，直接返回
      if (hash.has(target)) {
        return hash.get(target);
      }
      // 处理特殊对象类型
      const type = Object.prototype.toString.call(target);
      let clone;

      switch (type) {
        // 处理数组
        case '[object Array]':
          clone = [];
          hash.set(target, clone);
          target.forEach((item, index) => {
            clone[index] = deepClone(item, hash);
          });
          return clone;
        // 处理普通对象
        case '[object Object]':
          clone = {};
          hash.set(target, clone);
          // 处理 Symbol 作为 key 的情况
          Reflect.ownKeys(target).forEach(key => {
            clone[key] = deepClone(target[key], hash);
          });
          return clone;
        // 处理 Map
        case '[object Map]':
          clone = new Map();
          hash.set(target, clone);
          target.forEach((value, key) => {
            clone.set(deepClone(key, hash), deepClone(value, hash));
          });
          return clone;
        // 处理 Set
        case '[object Set]':
          clone = new Set();
          hash.set(target, clone);
          target.forEach(value => {
            clone.add(deepClone(value, hash));
          });
          return clone;
        // 处理 Date
        case '[object Date]':
          return new Date(target);
        // 处理 RegExp
        case '[object RegExp]':
          return new RegExp(target.source, target.flags);
        // 处理 Symbol（创建一个新的 Symbol，描述符相同）
        case '[object Symbol]':
          return Symbol(target.description);
        // 其他类型（如 Error、Promise 等）按需补充处理
        default:
          return target;
      }
    }

    // 测试用例
    const obj = {
      arr: [1, { a: 2 }, 3],
      map: new Map([['key', 'value']]),
      set: new Set([1, 2, 3]),
      date: new Date(),
      regex: /test/g,
      sym: Symbol('foo'),
      self: null // 用于循环引用
    };
    obj.self = obj; // 循环引用
    const cloned = deepClone(obj);
    console.log(cloned.arr !== obj.arr); // true
    console.log(cloned.map !== obj.map); // true
    console.log(cloned.self === cloned); // true（循环引用保持正确）
    console.log(cloned.sym === obj.sym); // false（Symbol 会被重新创建）

    // const arr = deepClone([1, { name: 1 }, []]);
  </script>
  <body></body>
</html>
